#pragma once

#include "Activity.h"

#include "ActivityEdge.h"
#include "ActivityGroup.h"
#include "ActivityNode.h"
#include "ActivityPartition.h"
#include "StructuredActivityNode.h"
#include "Variable.h"

namespace uml {

const bool Activity::isReadOnly_default_ = false;
const bool Activity::isSingleExecution_default_ = false;
Activity::Activity(const QString& umlType)
    : Behavior(umlType) {}

void Activity::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    Behavior::fromJson(json, errorList);
    JsonSerializable::fromJsonArray(edges_, "edges", json, errorList);
    JsonSerializable::fromJsonArray(groups_, "groups", json, errorList);
    isReadOnly_ = json.value("isReadOnly").toBool(isReadOnly_default_);
    isSingleExecution_ = json.value("isSingleExecution").toBool(isSingleExecution_default_);
    JsonSerializable::fromJsonArray(nodes_, "nodes", json, errorList);
    JsonSerializable::fromJsonArray(partitions_, "partitions", json, errorList);
    JsonSerializable::fromJsonArray(structuredNodes_, "structuredNodes", json, errorList);
    JsonSerializable::fromJsonArray(variables_, "variables", json, errorList);
}

void Activity::toJson(QJsonObject& json) {
    Behavior::toJson(json);
    JsonSerializable::toJsonArray(edges_, "edges", json);
    JsonSerializable::toJsonArray(groups_, "groups", json);
    if (isReadOnly_ != isReadOnly_default_) {
        json.insert("isReadOnly", isReadOnly_);
    }
    if (isSingleExecution_ != isSingleExecution_default_) {
        json.insert("isSingleExecution", isSingleExecution_);
    }
    JsonSerializable::toJsonArray(nodes_, "nodes", json);
    JsonSerializable::toJsonArray(partitions_, "partitions", json);
    JsonSerializable::toJsonArray(structuredNodes_, "structuredNodes", json);
    JsonSerializable::toJsonArray(variables_, "variables", json);
}

/// <summary>
/// edges getter
/// ActivityEdges expressing flow between the nodes of the Activity.
/// </summary>
vector<shared_ptr<ActivityEdge>>& Activity::edges() {
    return edges_;
}

/// <summary>
/// groups getter
/// Top-level ActivityGroups in the Activity.
/// </summary>
vector<shared_ptr<ActivityGroup>>& Activity::groups() {
    return groups_;
}

/// <summary>
/// isReadOnly getter
/// If true, this Activity must not make any changes to objects. The default is
/// false (an Activity may make nonlocal changes). (This is an assertion, not an
/// executable property. It may be used by an execution engine to optimize model
/// execution. If the assertion is violated by the Activity, then the model is
/// ill-formed.) 
/// </summary>
bool Activity::isReadOnly() const {
    return isReadOnly_;
}

/// <summary>
/// isReadOnly setter
/// If true, this Activity must not make any changes to objects. The default is
/// false (an Activity may make nonlocal changes). (This is an assertion, not an
/// executable property. It may be used by an execution engine to optimize model
/// execution. If the assertion is violated by the Activity, then the model is
/// ill-formed.) 
/// </summary>
void Activity::setIsReadOnly(bool value) {
    isReadOnly_ = value;
}

/// <summary>
/// isSingleExecution getter
/// If true, all invocations of the Activity are handled by the same execution.
/// </summary>
bool Activity::isSingleExecution() const {
    return isSingleExecution_;
}

/// <summary>
/// isSingleExecution setter
/// If true, all invocations of the Activity are handled by the same execution.
/// </summary>
void Activity::setIsSingleExecution(bool value) {
    isSingleExecution_ = value;
}

/// <summary>
/// nodes getter
/// ActivityNodes coordinated by the Activity.
/// </summary>
vector<shared_ptr<ActivityNode>>& Activity::nodes() {
    return nodes_;
}

/// <summary>
/// partitions getter
/// Top-level ActivityPartitions in the Activity.
/// </summary>
vector<shared_ptr<ActivityPartition>>& Activity::partitions() {
    return partitions_;
}

/// <summary>
/// structuredNodes getter
/// Top-level StructuredActivityNodes in the Activity.
/// </summary>
vector<shared_ptr<StructuredActivityNode>>& Activity::structuredNodes() {
    return structuredNodes_;
}

/// <summary>
/// variables getter
/// Top-level Variables defined by the Activity.
/// </summary>
vector<shared_ptr<Variable>>& Activity::variables() {
    return variables_;
}

} // namespace uml
